package com.newfiber.business.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.newfiber.business.constant.BusinessConstants;
import com.newfiber.business.domain.PatrolBasicInfo;
import com.newfiber.business.domain.PatrolPlan;
import com.newfiber.business.domain.PatrolTask;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanFixDate;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanFixFrequency;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanIntervalDate;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanQueryRequest;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanSaveRequest;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanUpdateRequest;
import com.newfiber.business.domain.request.patrolPlan.PatrolPlanUserSaveRequest;
import com.newfiber.business.domain.request.patrolTask.PatrolTaskUpdateRequest;
import com.newfiber.business.enums.*;
import com.newfiber.business.mapper.PatrolPlanMapper;
import com.newfiber.business.service.IPatrolBasicInfoService;
import com.newfiber.business.service.IPatrolLogService;
import com.newfiber.business.service.IPatrolPlanService;
import com.newfiber.business.service.IPatrolTaskService;
import com.newfiber.business.service.IPatrolUserService;
import com.newfiber.common.core.enums.EBoolean;
import com.newfiber.common.core.exception.ServiceException;
import com.newfiber.common.core.web.domain.BaseEntity;
import com.newfiber.common.core.web.service.BaseServiceImpl;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 巡查计划配置Service业务层处理
 *
 * @author X.K
 * @date 2023-02-17
 */
@Service
public class PatrolPlanServiceImpl extends BaseServiceImpl<PatrolPlanMapper, PatrolPlan> implements IPatrolPlanService {

    @Resource
    private PatrolPlanMapper patrolPlanMapper;

    @Resource
    private IPatrolBasicInfoService patrolBasicInfoService;

    @Resource
    private IPatrolUserService patrolUserService;

    @Resource
    private IPatrolTaskService patrolTaskService;

    @Resource
    private IPatrolLogService patrolLogService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public long insert(PatrolPlanSaveRequest request) {
        if (duplicateCheck(PatrolPlan::getPlanName, request.getPlanName())) {
            throw new ServiceException(String.format("巡查名称已存在：%s", request.getPlanName()));
        }

        PatrolBasicInfo patrolBasicInfo = patrolBasicInfoService.selectDetail(request.getBasicInfoId());

        // 巡查计划
        PatrolPlan patrolPlan = savePatrolPlan(request, patrolBasicInfo);

        // 巡查人员
        patrolUserService.save(EPatrolUserRefType.Task, patrolPlan.getId(), EPatrolUserType.Patrol,
                request.getPatrolUserList().stream().map(PatrolPlanUserSaveRequest::getUserId).collect(Collectors.toList()));

        // 巡查任务
        List<PatrolTask> patrolTasks = patrolTaskService.insertBatch(patrolPlan.getId(), request.getStatus(), request.getPatrolTaskList());

        // 生成巡查日志
        patrolLogService.insertBatch(patrolTasks);

        return Optional.of(patrolPlan).map(BaseEntity::getId).orElse(0L);
    }

    @NotNull
    private PatrolPlan savePatrolPlan(PatrolPlanSaveRequest request, PatrolBasicInfo patrolBasicInfo) {
        PatrolPlan patrolPlan = new PatrolPlan();
        BeanUtils.copyProperties(request, patrolPlan);
        patrolPlan.setPatrolType(patrolBasicInfo.getPatrolType());
        patrolPlan.setNumber(generatorNumber("PP", NumberFormat.DateSerialNumber));
        patrolPlan.setTaskCount((long) request.getPatrolTaskList().size());
        switch (EPatrolPlanFrequencyType.match(request.getPatrolFrequencyType())) {
            case IntervalDate:
                patrolPlan.setPatrolFrequencyContent(JSONObject.toJSONString(request.getPatrolPlanIntervalDate()));
                break;
            case FixFrequency:
                patrolPlan.setPatrolFrequencyContent(JSONObject.toJSONString(request.getPatrolPlanFixFrequency()));
                break;
            case FixDate:
                patrolPlan.setPatrolFrequencyContent(JSONObject.toJSONString(request.getPatrolPlanFixDate()));
                break;
            default:
                break;
        }
        save(patrolPlan);
        return patrolPlan;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(String ids) {
        return deleteLogic(ids);
    }

    @Override
    public boolean update(PatrolPlanUpdateRequest request) {
        if (duplicateCheck(PatrolPlan::getPlanName, request.getPlanName())) {
            throw new ServiceException(String.format("巡查名称已存在：%s", request.getPlanName()));
        }

        PatrolPlan patrolPlan = new PatrolPlan();
        BeanUtils.copyProperties(request, patrolPlan);
        return updateById(patrolPlan);
    }

    @Override
    public void updateTaskCount(Long planId, String field, String option) {
        patrolPlanMapper.updateFinishedTaskCount(planId, field, option);
    }

    @Override
    public boolean stop(String ids) {
        List<PatrolPlan> patrolPlanList = new ArrayList<>();
        Arrays.asList(ids.split(",")).forEach(id -> {
            if (patrolTaskService.count(Long.parseLong(id), EPatrolTaskStatus.Proceed) > 0) {
                throw new ServiceException("存在执行中的任务，无法停用");
            }
            // 更新巡查计划对应的巡查任务状态为 stopped
            PatrolTaskUpdateRequest request = new PatrolTaskUpdateRequest();
            request.setPlanId(Long.valueOf(id));
            patrolTaskService.updateWrapper(request);
            PatrolPlan patrolPlan = new PatrolPlan();
            patrolPlan.setId(Long.parseLong(id));
            patrolPlan.setStatus(EBoolean.False.getStringValue());
            patrolPlanList.add(patrolPlan);
        });
        return updateBatchById(patrolPlanList, patrolPlanList.size());
    }

    @Override
    public boolean startUse(Long planId) {
        // 更新plan状态未启用
        UpdateWrapper<PatrolPlan> patrolPlan = new UpdateWrapper<PatrolPlan>()
                .set("status", BusinessConstants.STATUS_1)
                .set("update_time", new Date())
                .eq("id", planId);
        update(patrolPlan);
        // 更新plan对应task状态为to_start
        return patrolTaskService.startUseTask(planId);
    }

    @Override
    public PatrolPlan selectDetail(Long id) {
        PatrolPlan patrolPlan = patrolPlanMapper.selectOneById(id);
        if (null == patrolPlan) {
            throw new ServiceException(String.format("%s ID=%s 的记录不存在", this.getClass().getSimpleName(), id));
        }
        wrapper(patrolPlan);
        return patrolPlan;
    }

    @Override
    public List<PatrolPlan> selectPage(PatrolPlanQueryRequest request) {
        return patrolPlanMapper.selectByCondition(request);
    }

    @Override
    public List<PatrolPlan> selectList(PatrolPlanQueryRequest request) {
        return patrolPlanMapper.selectByCondition(request);
    }

    private void wrapper(PatrolPlan patrolPlan) {
        switch (EPatrolPlanFrequencyType.match(patrolPlan.getPatrolFrequencyType())) {
            case IntervalDate:
                patrolPlan.setPatrolPlanIntervalDate(JSONObject.parseObject(patrolPlan.getPatrolFrequencyContent(), PatrolPlanIntervalDate.class));
                break;
            case FixFrequency:
                patrolPlan.setPatrolPlanFixFrequency(JSONObject.parseObject(patrolPlan.getPatrolFrequencyContent(), PatrolPlanFixFrequency.class));
                break;
            case FixDate:
                patrolPlan.setPatrolPlanFixDate(JSONObject.parseObject(patrolPlan.getPatrolFrequencyContent(), PatrolPlanFixDate.class));
                break;
            default:
                break;
        }
    }
}
